package panels;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;

public class JDoubleBox  extends JTextComponent implements ActionListener {

	public static final	String	VALUE_PROPERTY	= "VALUE_PROPERTY";
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private	BorderLayout	layout = null;
	private JButton			upButton = null;
	private JButton			downButton = null;
	private	JTextField		valueText = null;
	private	JLabel			nameLabel = null;
	private boolean			thisIsHorizontal = true;
	private boolean			resizeChangesOrientation = true;
	private double			minValue = Double.MIN_VALUE;
	private double			maxValue = Double.MAX_VALUE;

	private double			value = 0d;
	private boolean			visibleButtons = false;
	
	
	public String getFieldName() {
		if (nameLabel==null) { 
			return "";	
		} else {
			return nameLabel.getText();
		}
	}
	
	public void setFieldName(String text) {
		if (nameLabel!=null) {
			if (text!=null) {
				nameLabel.setText(text);
			} else {
				nameLabel.setText("");
			}
			placeButtons();
		}
	}
	
	public JDoubleBox() {
		layout = new BorderLayout();
		setLayout(layout);
		
		//
		// Create the controls
		//
		upButton = new JButton("+");
		downButton = new JButton("-");
		
		valueText = new JTextField();
		valueText.setText(Integer.toString(0));
		valueText.setHorizontalAlignment(JTextField.CENTER);
		valueText.setEnabled(true);
		
		nameLabel = new JLabel("");
		nameLabel.setText("");
		nameLabel.setHorizontalAlignment(JLabel.CENTER);
		
		//
		// Listen to the controls
		//
		upButton.addActionListener(this);
		downButton.addActionListener(this);
		valueText.addActionListener(this);
		
		//
		// Place the controls
		//
		add(valueText,BorderLayout.CENTER);
		setResizeChangesOrientation(true);
		placeButtons();
		
		this.setVisibleButtons(false);
	}
	
	public void placeButtons() {
		//
		// This will place the buttons in convient locations
		//
		this.remove(upButton);
		this.remove(downButton);
		this.remove(nameLabel);
		
		if (isHorizontal()==true) {
			if (this.isVisibleButtons()) {
				this.add(downButton,BorderLayout.WEST);
				this.add(upButton,BorderLayout.EAST);
			}
			if (getFieldName().length()>0) {
				this.add(nameLabel,BorderLayout.NORTH);
			}
		} else {
			if (isVisibleButtons())	{
				this.add(downButton,BorderLayout.SOUTH);
				this.add(upButton,BorderLayout.NORTH);
			}
			if (getFieldName().length()>0) {
				this.add(nameLabel,BorderLayout.WEST);
			}
		}
	}
	
	public void setSize(Dimension d) {
		super.setSize(d);
		if (isResizeChangesOrientation()) {
			setHorizontal(d.width > d.height);
		}	
	}
	
	public void setSize(int width, int height) {
		super.setSize(width,height);
		if (isResizeChangesOrientation()) {
			setHorizontal(width>height);
		}
	}

	public void setHorizontal(boolean value) {
		//
		// This determines the orientation of the buttons on the control
		// NOTE: When the size of the control changes, so to does the orientation
		//
		if (thisIsHorizontal != value) {
			placeButtons();
			thisIsHorizontal = value;
		}
	}

	public boolean isHorizontal() {
		return thisIsHorizontal;
	}

	public void setResizeChangesOrientation(boolean resizeChangesOrientation) {
		this.resizeChangesOrientation = resizeChangesOrientation;
	}

	public boolean isResizeChangesOrientation() {
		return resizeChangesOrientation;
	}

	public void setMinValue(double minValue) {
		if (minValue <= maxValue)
			this.minValue = minValue;
		if (this.value < this.minValue)
			this.value = this.minValue;
	}

	public double getMinValue() {
		return minValue;
	}

	public void setMaxValue(double maxValue) {
		if (maxValue>=minValue)
			this.maxValue = maxValue;
		if (this.value > this.maxValue)
			this.value = this.maxValue;
	}

	public double getMaxValue() {
		return maxValue;
	}

	public void setValue(double newValue) {
		double oldValue = getValue();
		if (newValue != oldValue && newValue>=minValue && newValue<=maxValue) {
			String	setText = Double.toString(newValue);

			value = newValue;
			setText = Double.toString(newValue);
			valueText.setText(setText);
			this.firePropertyChange(VALUE_PROPERTY, oldValue, newValue);
		}
	}

	public double getValue() {
		return value;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		//
		// This listens for events on all of it's components
		// I should update this to notify other controls that this
		// control has changed
		//
		if (e.getSource().equals(upButton)) {
			setValue(getValue()+1d);
		} else if (e.getSource().equals(downButton)) {
			setValue(getValue()-1d);
		} else if (e.getSource().equals(valueText)) {
			String	oldText = Double.toString(value);
			try {
				setValue( Double.parseDouble(valueText.getText()));
			} catch (NumberFormatException ex){
				valueText.setText(oldText);
			}
		}
	}

	public void setVisibleButtons(boolean visibleButtons) {
		this.visibleButtons = visibleButtons;
		placeButtons();
	}

	public boolean isVisibleButtons() {
		return visibleButtons;
	}

}